#include "server.h"

#include "base.qpb.h"
#include "user.qpb.h"
#include "gateway.qpb.h"
#include "friend.qpb.h"
#include "file.qpb.h"
#include "message_storage.qpb.h"
#include "message_transmit.qpb.h"
#include "speech_recognition.qpb.h"
#include "notify.qpb.h"

#include <QDateTime>
#include <QDebug>


//////////////////////////////////////////////////////////////////
/// 一些辅助函数
//////////////////////////////////////////////////////////////////

// 生成默认的 UserInfo 对象
bite_im::UserInfo makeUserInfo(int index, const QByteArray& avatar) {
    bite_im::UserInfo userInfo;
    userInfo.setUserId(QString::number(1000 + index));
    userInfo.setNickname("张三" + QString::number(index));
    userInfo.setDescription("个性签名" + QString::number(index));
    userInfo.setPhone("18612345678");
    userInfo.setAvatar(avatar);
    return userInfo;
}

// 生成默认的 TextMessageInfo 对象
bite_im::MessageInfo makeTextMessageInfo(int index, const QString& chatSessionId, const QByteArray& avatar) {
    bite_im::MessageInfo messageInfo;
    messageInfo.setMessageId(QString::number(3000 + index));
    messageInfo.setChatSessionId(chatSessionId);
    messageInfo.setTimestamp(getTime());
    messageInfo.setSender(makeUserInfo(index, avatar));

    bite_im::StringMessageInfo stringMessageInfo;
    stringMessageInfo.setContent("这是一条消息内容" + QString::number(index));

    bite_im::MessageContent messageContent;
    messageContent.setMessageType(bite_im::MessageTypeGadget::MessageType::STRING);
    messageContent.setStringMessage(stringMessageInfo);
    messageInfo.setMessage(messageContent);
    return messageInfo;
}

// 生成默认的 TextMessageInfo 对象
bite_im::MessageInfo makeImageMessageInfo(int index, const QString& chatSessionId, const QByteArray& avatar) {
    bite_im::MessageInfo messageInfo;
    messageInfo.setMessageId(QString::number(3000 + index));
    messageInfo.setChatSessionId(chatSessionId);
    messageInfo.setTimestamp(getTime());
    messageInfo.setSender(makeUserInfo(index, avatar));

    bite_im::ImageMessageInfo imageMessageInfo;
    imageMessageInfo.setFileId("testImage");
    // 真实服务器推送的消息数据里, 本身也就不带图片的正文. 只是 fileId.
    // 需要通过 fileId, 二次发起请求, 通过 getSingleFile 接口来获取到内容.
    // imageMessageInfo.setImageContent();

    bite_im::MessageContent messageContent;
    messageContent.setMessageType(bite_im::MessageTypeGadget::MessageType::IMAGE);
    messageContent.setImageMessage(imageMessageInfo);
    messageInfo.setMessage(messageContent);
    return messageInfo;
}

// 生成默认的 FileMessageInfo 对象
bite_im::MessageInfo makeFileMessageInfo(int index, const QString& chatSessionId, const QByteArray& avatar) {
    bite_im::MessageInfo messageInfo;
    messageInfo.setMessageId(QString::number(3000 + index));
    messageInfo.setChatSessionId(chatSessionId);
    messageInfo.setTimestamp(getTime());
    messageInfo.setSender(makeUserInfo(index, avatar));

    bite_im::FileMessageInfo fileMessageInfo;
    fileMessageInfo.setFileId("testFile");
    // 真实服务器推送的消息数据里, 本身也就不带图片的正文. 只是 fileId.
    // 需要通过 fileId, 二次发起请求, 通过 getSingleFile 接口来获取到内容.
    fileMessageInfo.setFileName("test.txt");
    // 此处文件大小, 无法设置. 由于 fileSize 属性, 不是 optional , 此处先设置一个 0 进来
    fileMessageInfo.setFileSize(0);

    bite_im::MessageContent messageContent;
    messageContent.setMessageType(bite_im::MessageTypeGadget::MessageType::FILE);
    messageContent.setFileMessage(fileMessageInfo);
    messageInfo.setMessage(messageContent);
    return messageInfo;
}

// 生成默认的 SpeechMessageInfo 对象
bite_im::MessageInfo makeSpeechMessageInfo(int index, const QString& chatSessionId, const QByteArray& avatar) {
    bite_im::MessageInfo messageInfo;
    messageInfo.setMessageId(QString::number(3000 + index));
    messageInfo.setChatSessionId(chatSessionId);
    messageInfo.setTimestamp(getTime());
    messageInfo.setSender(makeUserInfo(index, avatar));

    bite_im::SpeechMessageInfo speechMessageInfo;
    // 真实服务器推送的消息数据里, 本身也就不带图片的正文. 只是 fileId.
    // 需要通过 fileId, 二次发起请求, 通过 getSingleFile 接口来获取到内容.
    speechMessageInfo.setFileId("testSpeech");

    bite_im::MessageContent messageContent;
    messageContent.setMessageType(bite_im::MessageTypeGadget::MessageType::SPEECH);
    messageContent.setSpeechMessage(speechMessageInfo);
    messageInfo.setMessage(messageContent);
    return messageInfo;
}

//////////////////////////////////////////////////////////////////
/// HTTP 服务器
//////////////////////////////////////////////////////////////////
///
HttpServer* HttpServer::instance = nullptr;

HttpServer::HttpServer()
{
}

HttpServer *HttpServer::getInstance()
{
    if (HttpServer::instance == nullptr)
    {
        HttpServer::instance = new HttpServer();
    }

    return HttpServer::instance;
}

///
/// \brief HttpServer::init 初始化HttpServer
/// \return 初始化操作结果，true 表示成功，false 表示失败
///
bool HttpServer::init()
{
    // 绑定8000端口，可接收来自任意IP的访问
    // 返回值是int数值，表示成功绑定的端口号
    int result = httpServer.listen(QHostAddress::Any, 8000);

    // 以下为配置HTTP路由
    // 注意：此处的路由为Web开发术语：是指“请求路径”与“处理函数”的映射
    // 1. /ping
    httpServer.route("/ping", [](const QHttpServerRequest& req) {
        (void) req;
        qDebug() << "[http] 收到 ping 请求";
        return "pong";
    });

    // 2.




    return result == 8000;
}



//////////////////////////////////////////////////////////////////
/// HTTP 服务器
//////////////////////////////////////////////////////////////////
///
WebsocketServer* WebsocketServer::instance = nullptr;

WebsocketServer::WebsocketServer()
    : websocketServer("websocket server", QWebSocketServer::NonSecureMode)
{
}

WebsocketServer* WebsocketServer::getInstance()

{
    if (WebsocketServer::instance == nullptr)
    {
        WebsocketServer::instance = new WebsocketServer();
    }
    return WebsocketServer::instance;
}

// 针对 websocket 服务器进行初始化操作
bool WebsocketServer::init()
{
    // 1. 连接信号槽
    connect(&websocketServer, &QWebSocketServer::newConnection, this, [=]() {
        // 连接建立成功之后.
        qDebug() << "[websocket] 连接建立成功!";

        // 获取到用来通信的 socket 对象. nextPendingConnection 类似于 原生 socket 中的 accept
        QWebSocket* socket = websocketServer.nextPendingConnection();

        // 针对这个 socket 对象, 进行剩余信号的处理
        // 处理连接断开
        connect(socket, &QWebSocket::disconnected, this, [=]() {
            qDebug() << "[websocket] 连接断开!";
            disconnect(this, &WebsocketServer::sendTextResp, this, nullptr);
            disconnect(this, &WebsocketServer::sendFriendRemove, this, nullptr);
            disconnect(this, &WebsocketServer::sendAddFriendApply, this, nullptr);
            disconnect(this, &WebsocketServer::sendAddFriendProcess, this, nullptr);
            disconnect(this, &WebsocketServer::sendCreateChatSession, this, nullptr);
            disconnect(this, &WebsocketServer::sendImageResp, this, nullptr);
            disconnect(this, &WebsocketServer::sendFileResp, this, nullptr);
            disconnect(this, &WebsocketServer::sendSpeechResp, this, nullptr);
        });

        // 处理连接出错
        connect(socket, &QWebSocket::errorOccurred, this, [=](QAbstractSocket::SocketError error) {
            qDebug() << "[websocket] 连接出错! " << error;
        });

        // 处理收到来自客户端的文本消息
        connect(socket, &QWebSocket::textMessageReceived, this, [=](const QString& message) {
            qDebug() << "[websocket] 收到文本数据! message=" << message;
        });

        // 处理来自客户端的二进制消息
        connect(socket, &QWebSocket::binaryMessageReceived, this, [=](const QByteArray& byteArray) {
            qDebug() << "[websocket] 收到二进制数据! " << byteArray.length();
        });

        // 处理给客户端返回文本内容响应
        connect(this, &WebsocketServer::sendTextResp, this, [=]() {
            // 此处就可以捕获到 socket 对象, 从而可以通过 socket 对象给客户端返回数据.
            if (socket == nullptr || !socket->isValid()) {
                LOG() << "socket 对象无效!";
                return;
            }
            // 构造响应数据
            QByteArray avatar = loadFileToByteArray(":/resouce/image/defaultAvatar.png");
            bite_im::MessageInfo messageInfo = makeTextMessageInfo(this->messageIndex++, "2000", avatar);

            bite_im::NotifyNewMessage notifyNewMessage;
            notifyNewMessage.setMessageInfo(messageInfo);

            bite_im::NotifyMessage notifyMessage;
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(bite_im::NotifyTypeGadget::NotifyType::CHAT_MESSAGE_NOTIFY);
            notifyMessage.setNewMessageInfo(notifyNewMessage);

            // 序列化
            QByteArray body = notifyMessage.serialize(&this->serializer);

            // 发送消息给客户端
            socket->sendBinaryMessage(body);

            LOG() << "发送文本消息响应: " << messageInfo.message().stringMessage().content();
        });

        // 处理给客户端返回图片内容响应
        connect(this, &WebsocketServer::sendImageResp, this, [=]() {
            // 此处就可以捕获到 socket 对象, 从而可以通过 socket 对象给客户端返回数据.
            if (socket == nullptr || !socket->isValid()) {
                LOG() << "socket 对象无效!";
                return;
            }
            // 构造响应数据
            QByteArray avatar = loadFileToByteArray(":/resouce/image/defaultAvatar.png");
            bite_im::MessageInfo messageInfo = makeImageMessageInfo(this->messageIndex++, "2000", avatar);

            bite_im::NotifyNewMessage notifyNewMessage;
            notifyNewMessage.setMessageInfo(messageInfo);

            bite_im::NotifyMessage notifyMessage;
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(bite_im::NotifyTypeGadget::NotifyType::CHAT_MESSAGE_NOTIFY);
            notifyMessage.setNewMessageInfo(notifyNewMessage);

            // 序列化
            QByteArray body = notifyMessage.serialize(&this->serializer);

            // 发送消息给客户端
            socket->sendBinaryMessage(body);

            LOG() << "发送图片消息响应";
        });

        // 处理给客户端返回文件内容响应
        connect(this, &WebsocketServer::sendFileResp, this, [=]() {
            // 此处就可以捕获到 socket 对象, 从而可以通过 socket 对象给客户端返回数据.
            if (socket == nullptr || !socket->isValid()) {
                LOG() << "socket 对象无效!";
                return;
            }
            // 构造响应数据
            QByteArray avatar = loadFileToByteArray(":/resource/image/defaultAvatar.png");
            bite_im::MessageInfo messageInfo = makeFileMessageInfo(this->messageIndex++, "2000", avatar);

            bite_im::NotifyNewMessage notifyNewMessage;
            notifyNewMessage.setMessageInfo(messageInfo);

            bite_im::NotifyMessage notifyMessage;
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(bite_im::NotifyTypeGadget::NotifyType::CHAT_MESSAGE_NOTIFY);
            notifyMessage.setNewMessageInfo(notifyNewMessage);

            // 序列化
            QByteArray body = notifyMessage.serialize(&this->serializer);

            // 发送消息给客户端
            socket->sendBinaryMessage(body);

            LOG() << "发送文件消息响应";
        });

        // 处理给客户端返回语音内容响应
        connect(this, &WebsocketServer::sendSpeechResp, this, [=]() {
            // 此处就可以捕获到 socket 对象, 从而可以通过 socket 对象给客户端返回数据.
            if (socket == nullptr || !socket->isValid()) {
                LOG() << "socket 对象无效!";
                return;
            }
            // 构造响应数据
            QByteArray avatar = loadFileToByteArray(":/resource/image/defaultAvatar.png");
            bite_im::MessageInfo messageInfo = makeSpeechMessageInfo(this->messageIndex++, "2000", avatar);

            bite_im::NotifyNewMessage notifyNewMessage;
            notifyNewMessage.setMessageInfo(messageInfo);

            bite_im::NotifyMessage notifyMessage;
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(bite_im::NotifyTypeGadget::NotifyType::CHAT_MESSAGE_NOTIFY);
            notifyMessage.setNewMessageInfo(notifyNewMessage);

            // 序列化
            QByteArray body = notifyMessage.serialize(&this->serializer);

            // 发送消息给客户端
            socket->sendBinaryMessage(body);

            LOG() << "发送语音消息响应";
        });

        // 处理客户端的删除好友请求
        connect(this, &WebsocketServer::sendFriendRemove, this, [=]() {
            if (socket == nullptr || !socket->isValid()) {
                LOG() << "socket 对象无效";
                return;
            }

            bite_im::NotifyMessage notifyMessage;
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(bite_im::NotifyTypeGadget::NotifyType::FRIEND_REMOVE_NOTIFY);

            bite_im::NotifyFriendRemove notifyFriendRemove;
            notifyFriendRemove.setUserId("1000");
            notifyMessage.setFriendRemove(notifyFriendRemove);

            QByteArray body = notifyMessage.serialize(&serializer);
            socket->sendBinaryMessage(body);
            LOG() << "通知对方好友被删除 userId=1000";
        });

        // 处理客户端的申请添加为好友的请求
        connect(this, &WebsocketServer::sendAddFriendApply, this, [=]() {
            if (socket == nullptr || !socket->isValid()) {
                LOG() << "socket 对象无效";
                return;
            }

            bite_im::NotifyMessage notifyMessage;
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(bite_im::NotifyTypeGadget::NotifyType::FRIEND_ADD_APPLY_NOTIFY);

            QByteArray avatar = loadFileToByteArray(":/resource/image/defaultAvatar.png");
            bite_im::UserInfo userInfo = makeUserInfo(100, avatar);

            bite_im::NotifyFriendAddApply friendAddApply;
            friendAddApply.setUserInfo(userInfo);

            notifyMessage.setFriendAddApply(friendAddApply);

            QByteArray body = notifyMessage.serialize(&serializer);
            socket->sendBinaryMessage(body);
            LOG() << "通知对方好友申请数据";
        });

        // 处理通知客户端好友申请的结果
        connect(this, &WebsocketServer::sendAddFriendProcess, this, [=](bool agree) {
            if (socket == nullptr || !socket->isValid()) {
                LOG() << "socket 对象无效!";
                return;
            }

            bite_im::NotifyMessage notifyMessage;
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(bite_im::NotifyTypeGadget::NotifyType::FRIEND_ADD_PROCESS_NOTIFY);

            QByteArray avatar = loadFileToByteArray(":/resource/image/defaultAvatar.png");
            bite_im::UserInfo userInfo = makeUserInfo(100, avatar);

            bite_im::NotifyFriendAddProcess friendAddProcess;
            friendAddProcess.setUserInfo(userInfo);
            friendAddProcess.setAgree(agree);

            notifyMessage.setFriendProcessResult(friendAddProcess);

            QByteArray body = notifyMessage.serialize(&serializer);
            socket->sendBinaryMessage(body);
            LOG() << "通知好友申请的处理结果 userId=" << userInfo.userId() << ", agree=" << agree;
        });

        // 处理来自客户端创建聊天会话的请求
        connect(this, &WebsocketServer::sendCreateChatSession, this, [=]() {
            if (socket == nullptr || !socket->isValid()) {
                LOG() << "socket 对象无效!";
                return;
            }

            QByteArray avatar = loadFileToByteArray(":/resource/image/groupAvatar.png");

            bite_im::NotifyMessage notifyMessage;
            notifyMessage.setNotifyEventId("");
            notifyMessage.setNotifyType(bite_im::NotifyTypeGadget::NotifyType::CHAT_SESSION_CREATE_NOTIFY);

            bite_im::MessageInfo messageInfo = makeTextMessageInfo(0, "2100", avatar);

            bite_im::ChatSessionInfo chatSessionInfo;
            chatSessionInfo.setChatSessionId("2100");
            chatSessionInfo.setSingleChatFriendId("");
            chatSessionInfo.setChatSessionName("新的群聊");
            chatSessionInfo.setPrevMessage(messageInfo);
            chatSessionInfo.setAvatar(avatar);

            bite_im::NotifyNewChatSession newChatSession;
            newChatSession.setChatSessionInfo(chatSessionInfo);
            notifyMessage.setNewChatSessionInfo(newChatSession);

            // 序列化操作
            QByteArray body = notifyMessage.serialize(&serializer);

            // 通过 websocket 推送数据
            socket->sendBinaryMessage(body);
            LOG() << "通知创建会话!";
        });
    });

    // 2. 绑定端口, 启动服务
    bool ok = websocketServer.listen(QHostAddress::Any, 8001);
    return ok;
}








